package proxy

import (
	"bytes"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"io"
	"net/http"
	"net/url"
	"nvr-http-proxy/internal/constant"
	"nvr-http-proxy/internal/domain"
	"strings"
)

type Proxy struct {

	//登录后的Token
	NvrIpAndTokenMap map[string]domain.LoginResponse
}

func NewProxy(NvrIpAndTokenMap map[string]domain.LoginResponse) *Proxy {
	return &Proxy{NvrIpAndTokenMap: NvrIpAndTokenMap}
}

func (p *Proxy) ProxyHttpRequest(c *gin.Context) {
	ip := c.GetHeader("Nvr-Ip")
	if len(ip) == 0 {
		zap.S().Errorw("Nvr-Ip ===>>> Header不存在")
		return
	}
	parse, err := url.Parse(ip)
	if err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		zap.S().Errorf(err.Error())
		return
	}
	zap.S().Infof("===>>>请求的Ip地址为:%s", ip)
	v, ok := p.NvrIpAndTokenMap[ip]
	if !ok {
		c.JSON(500, gin.H{"message": "ip not found by NvrIpAndTokenMap"})
		return
	}

	// 读取请求体
	body, _ := c.GetRawData()
	// 创建请求
	nvpApi := parse.Scheme + "://" + parse.Host + c.Request.URL.Path
	// 统一增加参数 token
	queryParams := c.Request.URL.Query()
	queryParams.Add("token", v.Body.URLToken)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		zap.S().Errorf(err.Error())
		return
	}
	newUrl, err := url.Parse(nvpApi)
	newUrl.RawQuery = queryParams.Encode()
	req, err := http.NewRequest(c.Request.Method, newUrl.String(), bytes.NewReader(body))
	if err != nil {
		c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
		return
	}
	// 复制请求头
	for key, value := range c.Request.Header {
		req.Header.Set(key, strings.Join(value, ","))
	}
	zap.S().Infof("发送请求的Header:%v", req.Header)
	// 发送请求到后端服务
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
		return
	}
	defer resp.Body.Close()

	// 读取后端服务响应
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
		return
	}

	// 设置响应头并发送响应
	c.Header("Content-Type", "application/json")
	c.Status(resp.StatusCode)
	c.Writer.Write(responseBody)
}

func (p *Proxy) GetNvrConfig(c *gin.Context) {
	resp, err := http.Get(constant.EdgeNvrConfigHttpApi)
	if err != nil {
		zap.S().Errorw("调用盒子接口报错", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": "调用盒子接口报错",
		})
		return
	}
	// 读取后端服务响应
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		zap.S().Errorw("调用盒子接口报错", err)
		c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
		return
	}
	c.Header("Content-Type", "application/json")
	c.Status(resp.StatusCode)
	c.Writer.Write(responseBody)
}
